/*
 * jpeg_datasrc.c
 *
 *  David Lobato 2011 <dav.lobato@gmail.com>
 *
 *  Based on code found in libjpeg/jdatasrc.c from IJG
 *
 *  This file is part of Surveyor SVS player/stage driver.
 *
 *  Surveyor SVS player/stage driver is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  Surveyor SVS player/stage driver is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Surveyor SVS player/stage driver.
 *  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "jpeg_buffer_src.h"
#include <jerror.h>

static int debug = 0;

typedef struct {
	struct jpeg_source_mgr pub; /* public fields */

	JOCTET * buffer; /* start of buffer */
	size_t buffer_len;
	boolean start_of_file; /* have we gotten any data yet? */
} my_source_mgr;

typedef my_source_mgr * my_src_ptr;

/*
 * Initialize source --- called by jpeg_read_header
 * before any data is actually read.
 */

METHODDEF(void) init_source(j_decompress_ptr cinfo) {
	my_src_ptr src = (my_src_ptr) cinfo->src;

	/* We reset the empty-input-file flag for each image,
	 * but we don't clear the input buffer.
	 * This is correct behavior for reading a series of images from one source.
	 */
	src->start_of_file = TRUE;
}

/*
 * Fill the input buffer --- called whenever buffer is emptied.
 *
 * The whole data is supplied when mgr is created, so a call to
 * fill_input_buffer should be treated as an error.
 */

METHODDEF(boolean) fill_input_buffer(j_decompress_ptr cinfo) {
	ERREXIT(cinfo, JERR_INPUT_EOF);
	return TRUE;
}

/*
 * Skip data --- used to skip over a potentially large amount of
 * uninteresting data (such as an APPn marker).
 *
 * Writers of suspendable-input applications must note that skip_input_data
 * is not granted the right to give a suspension return.  If the skip extends
 * beyond the data currently in the buffer, the buffer can be marked empty so
 * that the next read will cause a fill_input_buffer call that can suspend.
 * Arranging for additional bytes to be discarded before reloading the input
 * buffer is the application writer's problem.
 */

METHODDEF(void) skip_input_data(j_decompress_ptr cinfo, long num_bytes) {
	my_src_ptr src = (my_src_ptr) cinfo->src;

	if (num_bytes > 0) {
		src->pub.next_input_byte += (size_t) num_bytes;
		src->pub.bytes_in_buffer -= (size_t) num_bytes;
	}
}

/*
 * Terminate source --- called by jpeg_finish_decompress
 * after all data has been read.  Often a no-op.
 *
 * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
 * application must deal with any cleanup that should happen even
 * for error exit.
 */

METHODDEF(void) term_source(j_decompress_ptr cinfo) {
	/* no work necessary here */
}

/*
 * Prepare for input from a data buffer.
 * The caller must have already allocated the buffer, and is responsible
 * for deallocating it after finishing decompression.
 */

GLOBAL(void) jpeg_buffer_src(j_decompress_ptr cinfo,
		unsigned char* buffer_src, size_t len) {
	my_src_ptr src;

	if (cinfo->src == NULL) { /* first time for this JPEG object? */
		cinfo->src = (struct jpeg_source_mgr *) (*cinfo->mem->alloc_small)(
				(j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof(my_source_mgr));
	}

	src = (my_src_ptr) cinfo->src;
	src->buffer = (JOCTET *) buffer_src;
	src->buffer_len = len;
	src->pub.init_source = init_source;
	src->pub.fill_input_buffer = fill_input_buffer;
	src->pub.skip_input_data = skip_input_data;
	src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
	src->pub.term_source = term_source;
	src->pub.bytes_in_buffer = src->buffer_len;
	src->pub.next_input_byte = src->buffer;
	if (debug){
		fprintf(stderr,"jpeg_buffer_src(): bytes in buffer=%d\n",(int)src->pub.bytes_in_buffer);
	}
}

